package com.xy.sql.xml;

import com.xy.sql.xml.core.XySQLKit;
import com.xy.sql.xml.core.XySQLResult;
import com.xy.sql.xml.itf.XySQLRegister;
import com.xy.sql.xml.kit.XySQLDataUtil;
import com.xy.sql.xml.node.XySQLSuperNode;
import com.xy.sql.xml.node.impl.XySQLMapperNode;
import com.xy.sql.xml.node.impl.XySQLModelItemNode;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 管理者
 */
public class XySQLManager {

    //缓存
    private static Map<String, XySQLMapperNode> mapperCache = new HashMap<>();

    /**
     * 解析
     *
     * @param dir
     * @return
     * @throws Exception
     */
    public static void addDirect(File dir) throws Exception {
        if (!dir.exists()) {
            return;
        }
        if (dir.isDirectory()) {
            for (File file : dir.listFiles()) {
                if (file.isDirectory()) {
                    addDirect(file);
                } else {
                    if (file.getName().endsWith(".xml")) {
                        addFile(file);
                    }
                }
            }
        } else {
            if (dir.getName().endsWith(".xml")) {
                addFile(dir);
            }
        }
    }


    /**
     * 解析
     *
     * @param sqlFile
     * @return
     * @throws Exception
     */
    private static void addFile(File sqlFile) throws Exception {
        if (!sqlFile.exists()) {
            return;
        }
        String text = new String(Files.readAllBytes(Paths.get(sqlFile.getAbsolutePath())));
        addSqlTxt(text);
    }

    /**
     * 解析     *
     *
     * @param text
     * @throws Exception
     */
    public static void addSqlTxt(String text) throws Exception {
        long start = System.currentTimeMillis();

        //格式化
        XySQLSuperNode root = XySQLKit.parse(text);
        if (root == null) {
            return;
        }

        XySQLRegister.getLogger().info("整体解析,耗时：" + (System.currentTimeMillis() - start));
        //理论上就一个
        XySQLMapperNode mapper = (XySQLMapperNode) root;
        //日志
        String namespace = mapper.getNamespace();
        if (namespace == null || namespace.trim().length() <= 0) {
            throw new Exception("Mapper的namespace不能为空，且必须唯一，否则会覆盖！");
        }
        mapperCache.put(namespace, mapper);
    }

    /**
     * 执行
     *
     * @param parameter
     * @return
     * @throws Exception
     */
    public static XySQLResult buildSql(String sqlId, Map<String, Object> parameter) throws Exception {
        int endIndex = sqlId.lastIndexOf(".");
        String modelName = sqlId.substring(0, endIndex);
        String id = sqlId.substring(endIndex + 1);
        XySQLMapperNode mapper = mapperCache.get(modelName);
        if (mapper == null) {
            return null;
        }
        if (parameter == null) {
            parameter = new HashMap<>();
        }
        XySQLResult vo = XySQLKit.bound(id, parameter, mapper);
        return vo;

    }

    /**
     * 转换结果
     *
     * @return
     * @throws Exception
     */
    public static List<Map<String, Object>> convertResult(String sqlId, List<Map<String, Object>> oriMap) throws Exception {
        int endIndex = sqlId.lastIndexOf(".");
        String modelName = sqlId.substring(0, endIndex);
        XySQLMapperNode mapper = mapperCache.get(modelName);
        List<Map<String, Object>> resMap = new ArrayList<>();
        if (mapper == null) {
            return resMap;
        }
        //根据模型定义，格式化返回参数
        Map<String, Map<String, String>> itemMap = mapper.getItemMap();
        for (Map<String, Object> data : oriMap) {
            Map<String, Object> newItem = new HashMap<>();
            for (Map.Entry<String, Object> entry : data.entrySet()) {
                newItem.put(entry.getKey(), entry.getValue());
                if (itemMap.containsKey(entry.getKey())) {
                    newItem.put(entry.getKey(), XySQLDataUtil.formatValue(itemMap.get(entry.getKey()).get(XySQLModelItemNode.ATT_FORMAT), entry.getValue()));
                }
            }
            resMap.add(newItem);
        }
        return resMap;

    }

}
